﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Linq;
using System.Web.Script.Serialization;
using System.Text;

using umbraco;
using umbraco.controls;
using umbraco.presentation.templateControls;
using umbraco.cms.businesslogic.web;
using umbraco.presentation.nodeFactory;

using umbraco.editorControls.userControlGrapper;

namespace AMD.Podcast.usercontrols
{
    /// <summary>
    /// This control us used to display nested drop down lists allowing the user to select multiple podcast categories
    /// </summary>
    public partial class AMD_Podcast_Categories : System.Web.UI.UserControl, IUsercontrolDataEditor
    {
        #region Variables
        String _umbval;                                             //Umbraco property value of selected categories
        XDocument _categories_xdoc;                                 //XML containing list of itunes categories
        protected StringBuilder _output = new StringBuilder();      //HTML output of selected categories
        #endregion

        #region Properties
        /// <summary>
        /// save/load the umbraco property value
        /// </summary>
        public object value
        {
            get
            {//Save property value
                XElement _saveValue = Get_XMLSaveValue();

                if (_saveValue != null)
                {
                    _umbval = _saveValue.ToString();
                }
                else
                {
                    _umbval = String.Empty;
                }

                PopulateControl();

                return _umbval;


            }

            set
            {//Load property value

                _umbval = String.Empty;


                if (string.IsNullOrEmpty(value.ToString()))
                {
                    _umbval = String.Empty;
                }
                else
                {
                    _umbval = value.ToString();
                }


            }
        }
        #endregion


        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                PopulateControl();
            }
        }



        #region Display Lists
        /// <summary>
        /// Build drop down lists for previously selected categories
        /// </summary>
        protected void PopulateControl()
        {

            if (!String.IsNullOrEmpty(_umbval))
            {

                XDocument _value = XDocument.Parse(_umbval);    //XML value with previously selected categories
                _categories_xdoc = XDocument.Load(HttpContext.Current.Request.MapPath("/usercontrols/AMD-Podcast/AMD-Podcast-Categories.xml")); //XML doc containing available categories


                foreach (XElement _selectedNode in _value.Root.Elements("category").ToList())
                {
                    IEnumerable<XElement> _results = _categories_xdoc.Descendants("category").Where(x => x.Attribute("text").Value == _selectedNode.Attribute("text").Value).ToList();

                    _output.Append("<div class=\"row\">" + Environment.NewLine);
                    _output.Append("<input class=\"row-value\" type=\"text\" name=\"rowvalue\" value=\"" + Get_Final_Value(_selectedNode) + "\">" + Environment.NewLine);
                    _output.Append(Add_DropDown_List(_categories_xdoc.Root, _selectedNode.Attribute("text").Value, 0) + Environment.NewLine);
                    _output.Append(Add_Child_Categories(_selectedNode, 0) + Environment.NewLine);
                    _output.Append("<div class=\"btn\">remove</div>" + Environment.NewLine);
                    _output.Append("</div>" + Environment.NewLine);
                }
            }
        }


        /// <summary>
        /// Iterate through child nodes in selected XML and add child drop-down lists. 
        /// Do final check for any child list to be added from _categories_xdoc
        /// </summary>
        /// <param name="_currentCategory">Current node in selected XML</param>
        /// <param name="_level">Incremental index for each list</param>
        /// <returns>String containing html for child lists</returns>
        String Add_Child_Categories(XElement _selectedNode, Int32 _level)
        {
            StringBuilder _output = new StringBuilder();

            if (_selectedNode.Nodes().Count() > 0)
            {
                XElement _childCategory = _selectedNode.Descendants("category").First();
                XElement _categoryNode = _categories_xdoc.Descendants("category").Where(x => x.Attribute("text").Value == _selectedNode.Attribute("text").Value).First();
                _level++;

                _output.Append(Add_DropDown_List(_categoryNode, _childCategory.Attribute("text").Value, _level) + Environment.NewLine);
                _output.Append(Add_Child_Categories(_childCategory, _level) + Environment.NewLine);
            }
            else
            {//Add unselected drop down list if there are child category nodes available
                XElement _categoryNode = _categories_xdoc.Descendants("category").Where(x => x.Attribute("text").Value == _selectedNode.Attribute("text").Value).First();

                if (_categoryNode != null)
                {
                    _level++;
                    _output.Append(Add_DropDown_List(_categoryNode, string.Empty, _level) + Environment.NewLine);
                }
            }


            return _output.ToString();
        }

        /// <summary>
        /// Loop through selected child nodes to find the final text value
        /// </summary>
        /// <param name="_selectedCategory">Current node in selected XML</param>
        /// <returns>text attribute from the final child node</returns>
        String Get_Final_Value(XElement _selectedCategory)
        {
            String _value = String.Empty;

            if (_selectedCategory.Elements("category").Count() > 0)
            {
                _value = Get_Final_Value(_selectedCategory.Elements("category").First());
            }
            else
            {
                _value = _selectedCategory.Attribute("text").Value;
            }

            return _value;
        }

        /// <summary>
        /// Build HTML for a category drop down list
        /// </summary>
        /// <param name="_categoryNode">Current parent-category node from _categories_xdoc, contains available options</param>
        /// <param name="_selectedText">Current selected text from umbraco property XML</param>
        /// <param name="_level">Incremental index for each list</param>
        /// <returns></returns>
        String Add_DropDown_List(XElement _categoryNode, String _selectedText, Int32 _level)
        {
            StringBuilder _list = new StringBuilder();

            if (_categoryNode.Elements("category").Count() > 0)
            {
                _list.Append("<select class=\"lvl-" + _level + "\">" + Environment.NewLine);
                _list.Append("<option value=\"\">Select...</option>" + Environment.NewLine);
                foreach (XElement _subCategory in _categoryNode.Elements("category").ToList())
                {
                    string _selected = (_subCategory.Attribute("text").Value == _selectedText) ? " selected=\"selected\" " : String.Empty;

                    _list.Append("<option value=\"" + _subCategory.Attribute("text").Value + "\" " + _selected + ">" + _subCategory.Attribute("text").Value + "</option>" + Environment.NewLine);
                }
                _list.Append("</select>" + Environment.NewLine);
            }

            return _list.ToString();
        }
        #endregion


        #region Save XML Value
        /// <summary>
        /// Build XML from list of selected list options
        /// </summary>
        /// <returns>XML list of selected values, maintaining hierarchy of source XML</returns>
        protected XElement Get_XMLSaveValue()
        {
            //Each row has a field called rowvalue that contains the value of the last selected drop-downlist
            String _rowValue = Request["rowvalue"] ?? String.Empty;
            XElement _saveValue = null;

            if (!String.IsNullOrEmpty(_rowValue))
            {
                _categories_xdoc = XDocument.Load(HttpContext.Current.Request.MapPath("/usercontrols/AMD-Podcast/AMD-Podcast-Categories.xml"));
                _saveValue = new XElement("categories");

                foreach (String _value in _rowValue.Split(','))
                {
                    var _categoryNode = _categories_xdoc.Descendants("category").Single(x => (String)x.Attribute("text").Value == _value.Trim());


                    if (_categoryNode != null)
                    {
                        XElement _newNode = new XElement("category");

                        if (_categoryNode.Attribute("text") != null)
                        {
                            _newNode.SetAttributeValue("text", _categoryNode.Attribute("text").Value);
                        }

                        while (_categoryNode.Parent != null)
                        {
                            _categoryNode = _categoryNode.Parent;

                            //Wrap current node in parent categories if available
                            if (_categoryNode.Attribute("text") != null)
                            {
                                _newNode = new XElement("category", _newNode);

                                if (_categoryNode.Attribute("text") != null)
                                {
                                    _newNode.SetAttributeValue("text", _categoryNode.Attribute("text").Value);
                                }
                            }
                        }

                        _saveValue.Add(_newNode);
                    }

                }

            }

            return _saveValue;
        }
        #endregion



    }
}